package com.songcha.library_common.ui.view.loading

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import com.songcha.library_common.R
import com.songcha.library_common.util.AlgorithmUtil
import com.songcha.library_common.util.FontUtil
import com.songcha.library_common.util.dp2px
import com.songcha.library_common.util.sp2px
import kotlin.math.absoluteValue

class CustomProgressBar
@JvmOverloads
constructor(
    context: Context,
    attrs: AttributeSet?=null,
    defStyle: Int = 0,
    defRes: Int = 0
) : View(context, attrs, defStyle, defRes) {
    private var mBackGroundColor=Color.parseColor("#e6e6e6")
    private var mProgressBackGroundColor=Color.GREEN
    private var mTextSize=16f.sp2px()
    private var mTextColor = Color.WHITE
    private var mProgress=100
    private var mBgPaint=Paint()
    private var mProgressBgPaint=Paint()
    private var mProgressTextPaint=Paint()
    private var mSelectPath=Path()
    private var mBgRect=RectF()
    private var mProgressBgRect=RectF()
    private var mIsRoundCap=false
    private var mShowProgressText=false
    private var mIsProgressFollowPercent = false
    private var mIsAnnular = false
    private var mAnnularRadius = 40f.dp2px()
    private var mShowPercentage = true
    private var mAnnularProgressStrokeWidth = 10f.dp2px()
    private var mAnnularPath = Path()
    private var mAnnularProgressPath = Path()
    private var mPathMeasure = PathMeasure()
    private var mAnnularBgPaint = Paint()
    private var mAnnularProgressPaint = Paint()


    init {
        initView(context,attrs)
    }

    companion object{
        private val PB_DEFAULT_WIDTH=150f.dp2px()
        private val PB_DEFAULT_HEIGHT=20f.dp2px()
    }

    private fun initView(context: Context, attrs: AttributeSet?){

        if(attrs!=null){
            val ta=context.obtainStyledAttributes(attrs, R.styleable.CustomProgressBar)
            mBackGroundColor=ta.getColor(R.styleable.CustomProgressBar_pb_background,Color.GRAY)
            mProgressBackGroundColor=ta.getColor(R.styleable.CustomProgressBar_pb_progress_background,Color.GREEN)
            mTextSize=ta.getDimension(R.styleable.CustomProgressBar_pb_text_size,16f.sp2px())
            mTextColor=ta.getColor(R.styleable.CustomProgressBar_pb_text_color,Color.WHITE)
            mIsRoundCap=ta.getBoolean(R.styleable.CustomProgressBar_pb_is_round_cap,false)
            mShowProgressText=ta.getBoolean(R.styleable.CustomProgressBar_pb_show_progress_text,false)
            mShowPercentage = ta.getBoolean(R.styleable.CustomProgressBar_pb_show_percentage,true)
            mIsProgressFollowPercent = ta.getBoolean(R.styleable.CustomProgressBar_pb_is_progress_follow_percent,false)
            mIsAnnular = ta.getBoolean(R.styleable.CustomProgressBar_pb_is_annular,false)
            mAnnularRadius = ta.getDimension(R.styleable.CustomProgressBar_pb_annular_radius,40f.dp2px())
            mAnnularProgressStrokeWidth = ta.getDimension(R.styleable.CustomProgressBar_pb_annular_stroke_width,10f.dp2px())
            ta.recycle()
        }

        initPaint()

    }

    private fun initPaint(){
        mBgPaint.style=Paint.Style.FILL
        mBgPaint.color=mBackGroundColor

        mProgressBgPaint.style=Paint.Style.STROKE
        if(mIsRoundCap)
            mProgressBgPaint.strokeCap=Paint.Cap.ROUND
        mProgressBgPaint.color=mProgressBackGroundColor

        mProgressTextPaint.color=mTextColor
        mProgressTextPaint.textSize=mTextSize

        mAnnularBgPaint.isAntiAlias=true
        mAnnularBgPaint.style=Paint.Style.STROKE
        mAnnularBgPaint.strokeWidth=mAnnularProgressStrokeWidth
        mAnnularBgPaint.color = mBackGroundColor

        mAnnularProgressPaint.isAntiAlias=true
        mAnnularProgressPaint.style=Paint.Style.STROKE
        mAnnularProgressPaint.strokeWidth=mAnnularProgressStrokeWidth
        mAnnularProgressPaint.color = mProgressBackGroundColor
        if(mIsRoundCap)
            mAnnularProgressPaint.strokeCap=Paint.Cap.ROUND

    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val widthMode=MeasureSpec.getMode(widthMeasureSpec)
        var widthSize=MeasureSpec.getSize(widthMeasureSpec)
        val heightMode=MeasureSpec.getMode(heightMeasureSpec)
        var heightSize=MeasureSpec.getSize(heightMeasureSpec)

        if(mIsAnnular){
            if(widthMode!=MeasureSpec.EXACTLY){
                widthSize = (2*(mAnnularRadius+mAnnularProgressStrokeWidth/2)).toInt()
            }
            if(heightMode!=MeasureSpec.EXACTLY){
                heightSize = (2*(mAnnularRadius+mAnnularProgressStrokeWidth/2)).toInt()
            }
        }else{
            if(widthMode!=MeasureSpec.EXACTLY){
                widthSize=PB_DEFAULT_WIDTH.toInt()
            }
            if(heightMode!=MeasureSpec.EXACTLY){
                heightSize=PB_DEFAULT_HEIGHT.toInt()
            }
        }

        setMeasuredDimension(widthSize,heightSize)
    }

    fun setBackground(backgroundColor:Int,progressColor:Int){
        mBackGroundColor=backgroundColor
        mProgressBackGroundColor=progressColor

        initPaint()
        initRect()
        invalidate()
    }

    private fun initRect(){
        val rdii= AlgorithmUtil.formatRadiiFloatArray(floatArrayOf((height/2).toFloat(),(height/2).toFloat(),(height/2).toFloat(),(height/2).toFloat()))
        val selectRoundRect=RectF(0f,0f,measuredWidth.toFloat(),measuredHeight.toFloat())
        mSelectPath.reset()
        mSelectPath.addRoundRect(selectRoundRect,rdii,Path.Direction.CW)
        mBgRect=RectF(0f,0f,measuredWidth.toFloat(),measuredHeight.toFloat())
        mProgressBgRect=RectF(0f,0f,0f,measuredHeight.toFloat())
        mProgressBgPaint.strokeWidth=measuredHeight.toFloat()
    }


    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)

        initRect()
    }


    fun setProgress(progress:Int){
        var p=progress
        if(p<0) p=0
        else if(p>100) p=100

        if(mProgress!=p){
            mProgress=progress
            invalidate()
        }
    }


    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        if(canvas==null)  return

        if(mIsAnnular){
            drawAnnularProgressBar(canvas)
        }else{
            drawLineProgressBar(canvas)
        }

        drawProgressText(canvas)

    }

    private fun drawProgressText(canvas: Canvas){
        if(mShowProgressText && mProgress>0){
            var str="$mProgress"
            if(mShowPercentage){
                str = str+"%"
            }
            val textRect= FontUtil.getTextBounds(str,mProgressTextPaint.textSize,false)?:return
            val fontMetrics=FontUtil.getFontMetrics(mProgressTextPaint.textSize,false)?:return
            val textHeight=(fontMetrics.top.absoluteValue+fontMetrics.bottom)

            var textX = (width/2-textRect.width()/2).toFloat()
            if(!mIsAnnular && mIsProgressFollowPercent){
                textX = (width*mProgress/100).toFloat() - textRect.width()
            }
            canvas.drawText(str,textX,(height/2)+(textHeight/2-fontMetrics.bottom),mProgressTextPaint)
        }
    }

    private fun drawLineProgressBar(canvas: Canvas){
        canvas.clipPath(mSelectPath)
        canvas.drawRoundRect(mBgRect,(height/2).toFloat(),(height/2).toFloat(),mBgPaint)

        canvas.drawLine(0f,(height/2).toFloat(),(width*mProgress/100).toFloat(),(height/2).toFloat(),mProgressBgPaint)
    }

    private fun drawAnnularProgressBar(canvas: Canvas){
        //radius = width/2-storkWidth/2
        mAnnularPath.reset()
        mAnnularPath.addCircle(width/2f,height/2f,mAnnularRadius,Path.Direction.CW)
        canvas.drawPath(mAnnularPath,mAnnularBgPaint)

        mAnnularProgressPath.reset()
        mPathMeasure.setPath(mAnnularPath,false)
        val stopD = (mProgress/100f)*mPathMeasure.length
        mPathMeasure.getSegment(0f,stopD,mAnnularProgressPath,true)
        canvas.drawPath(mAnnularProgressPath,mAnnularProgressPaint)

    }


}